package com.zhuhjay.common.base.expand;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.zhuhjay.common.base.config.IpResolveConfig;
import com.zhuhjay.common.base.constant.TimeConstant;
import com.zhuhjay.common.base.util.SpringContextHolder;
import lombok.extern.slf4j.Slf4j;

/**
 * IP地址解析
 * @author ZhuHJay
 * @date 2024/2/28 11:47
 */
public interface IpResolve {
    /** 名称 */
    String resolveName();
    /** 是否启用 */
    boolean enable();
    /** 解析IP地址 */
    String resolve(String ip);

    @Slf4j
    enum IpResolveStrategy implements IpResolve {
        /** 太平洋网络免费解析, 放置于首位, 优先使用 *DEFAULT* */
        TaiPingYangNet {
            private static final String URL = "https://whois.pconline.com.cn/ipJson.jsp";

            @Override
            public String resolveName() {
                return "tai-ping-yang-net";
            }

            @Override
            public boolean enable() {
                return true;
            }

            public String resolve(String ip) {
                try {
                    String body = HttpUtil.get(URL + "?ip=" + ip + "&json=true", TimeConstant.SECOND);
                    if (StrUtil.isBlank(body)) {
                        return "";
                    }
                    // 处理返回值的json数据(原始数据包含\n)
                    String s = CharSequenceUtil.removeAllLineBreaks(body);
                    if (!JSONUtil.isTypeJSON(s)) {
                        log.error("[{}]获取IP[{}]位置失败\n===body===\n{}", resolveName(), ip, body);
                        return "";
                    }
                    JSON parse = JSONUtil.parse(s);
                    String pro = parse.getByPath("pro", String.class);
                    String city = parse.getByPath("city", String.class);
                    String err = parse.getByPath("err", String.class);
                    if (StrUtil.isNotBlank(err)) {
                        log.error("[{}]获取IP[{}]位置失败：{}", resolveName(), ip, err);
                        return "";
                    }
                    return StrUtil.format("{} {}", pro, city);
                } catch (Exception e) {
                    log.error("[{}]获取IP[{}]位置失败：{}", resolveName(), ip, e.getMessage());
                    return "";
                }
            }
        },

        /** 腾讯地图解析, 需要提供 key */
        TengXunMap {
            private static final String URL = "https://apis.map.qq.com/ws/location/v1/ip";

            @Override
            public String resolveName() {
                return "teng-xun-map";
            }

            @Override
            public boolean enable() {
                IpResolveConfig config = SpringContextHolder.getBean(IpResolveConfig.class);
                return config.getTx().isEnable();
            }

            @Override
            public String resolve(String ip) {
                IpResolveConfig.TengXunMapProp txConfig = SpringContextHolder.getBean(IpResolveConfig.class).getTx();
                try {
                    String body = HttpUtil.get(URL + "?" + txConfig.buildQuery(ip), TimeConstant.SECOND);
                    if (StrUtil.isBlank(body)) {
                        return "";
                    }
                    // 处理返回值的json数据
                    JSON parse = JSONUtil.parse(body);
                    if (!JSONUtil.isTypeJSON(body)) {
                        log.error("[{}]获取IP[{}]位置失败\n===body===\n{}", resolveName(), ip, body);
                        return "";
                    }
                    int status = parse.getByPath("status", Integer.class);
                    if (status != 0) {
                        String message = parse.getByPath("message", String.class);
                        log.error("[{}]获取IP[{}]位置失败：{}", resolveName(), ip, message);
                        return "";
                    }
                    String pro = parse.getByPath("result.ad_info.province", String.class);
                    String city = parse.getByPath("result.ad_info.city", String.class);
                    return StrUtil.format("{} {}", pro, city);
                } catch (Exception e) {
                    log.error("[{}]获取IP[{}]位置失败：{}", resolveName(), ip, e.getMessage());
                    return "";
                }
            }
        };
    }
}
